#ifndef __MCS__FUNCTION_EXPRESSION__HPP
#define __MCS__FUNCTION_EXPRESSION__HPP

#include "Expression.hpp"
#include "FunctionArgumentList.hpp"
#include "FunctionFactory.hpp"
#include "FunctionNotFoundException.hpp"
#include "ScriptException.hpp"

/// Operator or function invocation
class FunctionExpression : public Expression
{
public:
	FunctionExpression(SourceLocation const & location, String const & name, ptr<FunctionArgumentList> args)
		: Expression(location)
		, name_(name), args_(args)
	{
	}

	virtual void init(Block * parentBlock)
	{
		Expression::init(parentBlock);
		
		args_->init(parentBlock);
		FunctionSignature signature = args_->calcSignature(name_);
		func_ = parentBlock->functionFactory()->getFunction(signature);
		
		if(!func_)
		{
			throw FunctionNotFoundException(signature, location());
		}

	}

	virtual ptr<Value> evaluate() const
	{
		std::vector< ptr<Value> > invokeArgs;
		invokeArgs.reserve(args_->count());

		for(size_t i=0; i<args_->count(); ++i)
		{
			invokeArgs.push_back(args_->arg(i)->evaluate());
		}

		ptr<Value> retVal;

		try
		{
			retVal = func_->invoke(invokeArgs);
		}
		catch(ScriptException const & ex)
		{
			throw ScriptExceptionException(location(), ex);
		}

		return retVal;
	}

	virtual Value::DataType dataType() const
	{
		return func_->returnType();
	}
private:
	String name_;
	ptr<FunctionArgumentList> args_;
	ptr<Function> func_;
};

#endif //__MCS__FUNCTION_EXPRESSION__HPP
